home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Internet Info 1994 March
/
Internet Info CD-ROM (Walnut Creek) (March 1994).iso
/
networking
/
ip
/
ka9q
/
src890906.arc
/
AX25CMD.C
< prev
next >
Wrap
C/C++ Source or Header
|
1989-08-19
|
14KB
|
638 lines
#include <stdio.h>
#include "global.h"
#include "mbuf.h"
#include "timer.h"
#include "proc.h"
#include "iface.h"
#include "ax25.h"
#include "lapb.h"
#include "cmdparse.h"
#include "socket.h"
#include "ax25tnc.h"
#include "ax_mbx.h"
#include "session.h"
#include "tty.h"
#include "nr4.h"
#include "commands.h"
extern char Notval[];
static void ax_in __ARGS((int unused,void *tnc1,void *p));
static int doaxirtt __ARGS((int argc,char *argv[],void *p));
static int doaxkick __ARGS((int argc,char *argv[],void *p));
static int doaxreset __ARGS((int argc,char *argv[],void *p));
static int doaxroute __ARGS((int argc,char *argv[],void *p));
static int doaxstat __ARGS((int argc,char *argv[],void *p));
static int doaxwindow __ARGS((int argc,char *argv[],void *p));
static int dodigipeat __ARGS((int argc,char *argv[],void *p));
static int domaxframe __ARGS((int argc,char *argv[],void *p));
static int domycall __ARGS((int argc,char *argv[],void *p));
static int don2 __ARGS((int argc,char *argv[],void *p));
static int dopaclen __ARGS((int argc,char *argv[],void *p));
static int dopthresh __ARGS((int argc,char *argv[],void *p));
static int dot3 __ARGS((int argc,char *argv[],void *p));
static int doversion __ARGS((int argc,char *argv[],void *p));
char *Ax25states[] = {
"Disconnected",
"Listening",
"Conn pending",
"Disc pending",
"Connected",
"Recovery",
"Frame Reject",
};
/* Ascii explanations for the disconnect reasons listed in lapb.h under
* "reason" in ax25_cb
*/
char *Axreasons[] = {
"Normal",
"DM received",
"Timeout"
};
static struct cmds Axcmds[] = {
"digipeat", dodigipeat, 0, 0, NULLCHAR,
"irtt", doaxirtt, 0, 0, NULLCHAR,
"kick", doaxkick, 0, 2, "ax25 kick <axcb>",
"maxframe", domaxframe, 0, 0, NULLCHAR,
"mycall", domycall, 0, 0, NULLCHAR,
"paclen", dopaclen, 0, 0, NULLCHAR,
"pthresh", dopthresh, 0, 0, NULLCHAR,
"reset", doaxreset, 0, 2, "ax25 reset <axcb>",
"retry", don2, 0, 0, NULLCHAR,
"route", doaxroute, 0, 0, NULLCHAR,
"status", doaxstat, 0, 0, NULLCHAR,
"t3", dot3, 0, 0, NULLCHAR,
"version", doversion, 0, 0, NULLCHAR,
"window", doaxwindow, 0, 0, NULLCHAR,
NULLCHAR,
};
/* Multiplexer for top-level ax25 command */
int
doax25(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return subcmd(Axcmds,argc,argv,p);
}
static
doaxreset(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct ax25_cb *axp;
axp = (struct ax25_cb *)ltop(htol(argv[1]));
if(!ax25val(axp)){
printf(Notval);
return 1;
}
reset_ax25(axp);
return 0;
}
/* Display AX.25 link level control blocks */
static
doaxstat(argc,argv,p)
int argc;
char *argv[];
void *p;
{
register int i;
register struct ax25_cb *axp;
char tmp[10];
if(argc < 2){
printf(" &AXB Snd-Q Rcv-Q Remote State\n");
for(i=0;i<NHASH;i++){
for(axp = Ax25_cb[i];axp != NULLAX25; axp = axp->next){
pax25(tmp,&axp->remote);
printf("%8lx %-8d%-8d%-10s%s\n",
ptol(axp),
len_q(axp->txq),len_mbuf(axp->rxq),
tmp,Ax25states[axp->state]);
}
}
return 0;
}
axp = (struct ax25_cb *)ltop(htol(argv[1]));
if(!ax25val(axp)){
printf(Notval);
return 1;
}
st_ax25(axp);
return 0;
}
/* Dump one control block */
void
st_ax25(axp)
register struct ax25_cb *axp;
{
char tmp[10];
if(axp == NULLAX25)
return;
printf(" &AXB Remote RB V(S) V(R) Unack P Retry State\n");
pax25(tmp,&axp->remote);
printf("%8lx %-9s",ptol(axp),tmp);
putchar(axp->flags.rejsent ? 'R' : ' ');
putchar(axp->flags.remotebusy ? 'B' : ' ');
printf(" %4d %4d",axp->vs,axp->vr);
printf(" %02u/%02u %u",axp->unack,axp->maxframe,axp->proto);
printf(" %02u/%02u",axp->retries,axp->n2);
printf(" %s\n",Ax25states[axp->state]);
printf("SRT = %lu ",axp->srt * MSPTICK);
printf("T1: ");
if(run_timer(&axp->t1))
printf("%lu",read_timer(&axp->t1) * MSPTICK);
else
printf("stop");
printf("/%lu ms; ",dur_timer(&axp->t1) * MSPTICK);
printf("T3: ");
if(run_timer(&axp->t3))
printf("%lu",read_timer(&axp->t3) * MSPTICK);
else
printf("stop");
printf("/%lu ms\n",dur_timer(&axp->t3) * MSPTICK);
}
/* Display or change our AX.25 address */
static
domycall(argc,argv,p)
int argc;
char *argv[];
void *p;
{
char buf[15];
if(argc < 2){
pax25(buf,&Mycall);
printf("%s\n",buf);
return 0;
}
if(setcall(&Mycall,argv[1]) == -1)
return -1;
Mycall.ssid |= E;
return 0;
}
/* Control AX.25 digipeating */
static
dodigipeat(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setbool(&Digipeat,"Digipeat",argc,argv);
}
static
doversion(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setshort(&Axversion,"AX25 version",argc,argv);
}
static
doaxirtt(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setlong(&Axirtt,"Initial RTT (ms)",argc,argv);
}
/* Set idle timer */
static
dot3(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setlong(&T3init,"Idle poll timer (ms)",argc,argv);
}
/* Set retry limit count */
static
don2(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setshort(&N2,"Retry limit",argc,argv);
}
/* Force a retransmission */
static
doaxkick(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct ax25_cb *axp;
axp = (struct ax25_cb *)ltop(htol(argv[1]));
if(!ax25val(axp)){
printf(Notval);
return 1;
}
kick_ax25(axp);
return 0;
}
/* Set maximum number of frames that will be allowed in flight */
static
domaxframe(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setshort(&Maxframe,"Window size (frames)",argc,argv);
}
/* Set maximum length of I-frame data field */
static
dopaclen(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setshort(&Paclen,"Max frame length (bytes)",argc,argv);
}
/* Set size of I-frame above which polls will be sent after a timeout */
static
dopthresh(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setshort(&Pthresh,"Poll threshold (bytes)",argc,argv);
}
/* Set high water mark on receive queue that triggers RNR */
static
doaxwindow(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setshort(&Axwindow,"AX25 receive window (bytes)",argc,argv);
}
/* End of ax25 subcommands */
/* Initiate interactive AX.25 connect to remote station */
int
doconnect(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct sockaddr_ax fsocket;
struct session *sp;
/* Allocate a session descriptor */
if((sp = newsession(argv[2],AX25TNC)) == NULLSESSION){
printf("Too many sessions\n");
freeargs(argc,argv);
return 1;
}
if((sp->s = socket(AF_AX25,SOCK_STREAM,0)) == -1){
freesession(sp);
printf("Can't create socket\n");
freeargs(argc,argv);
return 1;
}
fsocket.sax_family = AF_AX25;
setcall(&fsocket.ax25_addr,argv[2]);
strncpy(fsocket.iface,argv[1],ILEN);
freeargs(argc,argv);
printf("Trying %s...\n",psocket((struct sockaddr *)&fsocket));
return axnrconnect(sp, (char *)&fsocket, sizeof(struct sockaddr_ax));
}
/* Generic interactive connect routine, used by both AX.25 and NET/ROM */
int
axnrconnect(sp, fsocket, len)
struct session *sp;
char *fsocket;
int len;
{
struct mbuf *bp;
char *cp;
Current = sp;
Mode = CONV_MODE;
sp->cb.ax25 = (struct ax25tnc *)calloc(1,sizeof(struct ax25tnc));
sp->cb.ax25->session = sp;
sp->cb.ax25->output = Curproc;
if(connect(sp->s,fsocket,len) == -1){
printf("%s session %u failed: %s errno %d\n",
Sestypes[sp->type],(unsigned)(sp-Sessions),
sockerr(sp->s),errno);
close_s(sp->s);
free((char *)sp->cb.ax25);
freesession(sp);
return 1;
}
printf("%s session %u connected to %s\n",Sestypes[sp->type],
(unsigned)(sp-Sessions),sp->name);
sp->cb.ax25->output = Curproc;
sp->cb.ax25->input = newproc("ax_in",1024,ax_in,0,sp->cb.ax25,NULL);
for(;;){
while(sp->input == NULLBUF)
pwait(&sp->input);
bp = dequeue(&sp->input);
/* If we're recording, record it */
if(sp->record != NULLFILE)
write_p(sp->record,bp);
/* Get rid of the trailing newline */
if((cp = strchr(bp->data,'\n')) != NULLCHAR){
*cp = '\0';
bp->cnt--;
}
if(send_mbuf(sp->s,bp,0,NULLCHAR,0) == -1)
break;
}
killproc(sp->cb.ax25->input);
close_s(sp->s);
free(sp->cb.ax25);
freesession(sp);
return 0;
}
/* Display and modify AX.25 routing table */
static int
doaxroute(argc,argv,p)
int argc;
char *argv[];
void *p;
{
char buf[30];
int i,j,ndigis;
register struct ax_route *axr;
struct ax25_addr target,digis[MAXDIGIS];
if(argc < 2){
printf("Target Type Digipeaters\n");
for(i=0;i<NAXROUTE;i++){
for(axr = Ax_routes[i];axr != NULLAXR;axr = axr->next){
pax25(buf,&axr->target);
printf("%-10s%-6s",buf,
axr->type == AX_LOCAL ? "Local":"Auto");
for(j=0;j<axr->ndigis;j++){
pax25(buf,&axr->digis[j]);
printf(" %s",buf);
}
printf("\n");
}
}
return 0;
}
if(argc < 3){
printf("Usage: ax25 route add <target> [digis...]\n");
printf(" ax25 route drop <target>\n");
return 1;
}
if(setcall(&target,argv[2]) == -1){
printf("Bad target %s\n",argv[2]);
return 1;
}
switch(argv[1][0]){
case 'a': /* Add route */
if(argc < 3){
printf("Usage: ax25 route add <target> [digis...]\n");
return 1;
}
ndigis = argc - 3;
for(i=0;i<ndigis;i++){
if(setcall(&digis[i],argv[i+3]) == -1){
printf("Bad digipeater %s\n",argv[i+3]);
return 1;
}
}
if(ax_add(&target,AX_LOCAL,&digis[0],ndigis) == NULLAXR){
printf("Failed\n");
return 1;
}
break;
case 'd': /* Drop route */
if(ax_drop(&target) == -1){
printf("Not in table\n");
return 1;
}
break;
default:
printf("Unknown command %s\n",argv[1]);
return 1;
}
return 0;
}
/* Upload process for both AX.25 and NET/ROM sessions */
void
ax_upload(unused,sp1,p)
int unused;
void *sp1;
void *p;
{
struct mbuf *bp;
char *cp;
int c,bufsize;
struct session *sp;
sp = (struct session *)sp1;
/* NET/ROM is a sequenced packet protocol, so we have to make sure
that the length of each packet is within legal limits */
if (sp->type == NRSESSION)
bufsize = NR4MAXINFO;
else
bufsize = BUFSIZ;
for(;;){
bp = alloc_mbuf(bufsize);
cp = bp->data;
while(bp->cnt < bufsize){
if((c = getc(sp->upload)) == EOF)
break;
if(c == '\r')
continue;
if(c == '\n')
c = '\r';
*cp++ = c;
bp->cnt++;
}
if(bp->cnt == 0){
free_p(bp);
break;
} else if(send_mbuf(sp->s,bp,0,NULLCHAR,0) == -1)
break;
}
fclose(sp->upload);
sp->upload = NULLFILE;
free(sp->ufile);
sp->ufile = NULLCHAR;
sp->cb.ax25->upload = NULLPROC;
}
/* AX.25 TNC receive process, used by both AX.25 and NET/ROM sessions */
static void
ax_in(unused,tnc1,p)
int unused;
void *tnc1;
void *p;
{
char c;
struct session *sp;
char *cp;
struct mbuf *bp;
int s;
struct ax25tnc *tnc;
tnc = (struct ax25tnc *)tnc1;
sp = tnc->session;
s = sp->s;
for(;;){
if(recv_mbuf(s,&bp,0,0,NULLCHAR,0) == -1)
break;
while(pullup(&bp,&c,1) == 1){
/* Suspend output if we're not current */
while(Current != sp || Mode != CONV_MODE)
pwait(sp);
putchar(c);
if(c == '\r')
putchar('\n');
if(sp->record != NULLFILE){
#ifdef UNIX
if(c != '\r')
#endif
putc(c,sp->record);
if(c == '\r')
putc('\n',sp->record);
}
}
}
/* Close seen from remote host */
cp = sockerr(s);
printf("%s session %u closed: %s\n", Sestypes[sp->type],
(unsigned)(sp - Sessions),
cp != NULLCHAR ? cp : "EOF");
close_s(s);
tnc->input = NULLPROC;
killproc(tnc->output);
free((char *)tnc);
freesession(sp);
}
int
ax25start(argc,argv,p)
int argc;
char *argv[];
void *p;
{
int s;
char buf[80];
freeargs(argc,argv); /* Args are not used */
if (Axi_sock != -1)
return 0;
psignal(Curproc,0); /* Don't keep the parser waiting */
chname(Curproc,"AX25 listener");
Axi_sock = socket(AF_AX25,SOCK_STREAM,0);
/* bind() is done automatically */
if(listen(Axi_sock,1) == -1){
close_s(Axi_sock);
return -1;
}
for(;;){
if((s = accept(Axi_sock,NULLCHAR,NULLINT)) == -1)
break; /* Service is shutting down */
if(Ax25mbox){
/* Eat the line that triggered the connection
* and then start the mailbox
*/
recvline(s,buf,80);
newproc("mbox",2048,mbx_incom,s,(void *)AX25TNC,NULL);
} else
newproc("in_ax25",2048,axnrhandle,s,(void *)AX25TNC,NULL);
}
close_s(Axi_sock);
Axi_sock = -1;
return 0;
}
int
ax250(argc,argv,p)
int argc;
char *argv[];
void *p;
{
close_s(Axi_sock);
Axi_sock = -1;
return 0;
}
/* This function handles both incoming AX25 and NETROM sessions */
void
axnrhandle(s,t,p)
int s;
void *t;
void *p;
{
int type;
struct session *sp;
char buf[20], *cp;
struct mbuf *bp;
char addr[MAXSOCKSIZE];
int len = MAXSOCKSIZE;
type = (int)t;
sockowner(s,Curproc); /* We own it now */
sprintf(buf,"open %s",Sestypes[type]);
log(s,buf);
/* Allocate a session descriptor */
if((sp = newsession(NULLCHAR,type)) == NULLSESSION){
usprintf(s,"Too many sessions\n");
close_s(s);
}
getpeername(s,addr,&len);
printf("\007Incoming %s session %u from %s\007\n",Sestypes[type],
(unsigned)(sp - Sessions),psocket(addr));
sp->cb.ax25 = (struct ax25tnc *)calloc(1,sizeof(struct ax25tnc));
sp->cb.ax25->session = sp;
sp->cb.ax25->output = Curproc;
sp->s = s;
sp->ttymode = TTY_EDIT|TTY_ECHO;
sp->cb.ax25->input = newproc("ax_in",1024,ax_in,0,sp->cb.ax25,NULL);
for(;;){
while(sp->input == NULLBUF)
pwait(&sp->input);
bp = dequeue(&sp->input);
/* If we're recording, record it */
if(sp->record != NULLFILE)
write_p(sp->record,bp);
/* Get rid of the trailing newline */
if((cp = strchr(bp->data,'\n')) != NULLCHAR){
*cp = '\0';
bp->cnt--;
}
if(send_mbuf(s,bp,0,NULLCHAR,0) == -1)
break;
}
killproc(sp->cb.ax25->input);
close_s(s);
free((char *)sp->cb.ax25);
freesession(sp);
}